package com.zyg.cod.service;


import com.alibaba.fastjson.JSONObject;
import com.zyg.cod.util.Base64Util;
import com.zyg.cod.util.Document2MapUtil;
import com.zyg.cod.util.WriteFileUtil;
import org.apache.log4j.Logger;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 解密服务
 * 将第三方通道的带传输头的回执报文进行解密，解密成业务报文后移动到企业ERP特定目录下
 */
public class DecryptXmlService {
    private static Logger log=Logger.getLogger(DecryptXmlService.class);

    private static SAXReader saxReader = new SAXReader();
    private static String beforeDecryptPath;//解密前回执报文路径
    private static String afterDecryptPath;//解密后的回执报文路径
    public DecryptXmlService(String beforeDecryptPath,String afterDecryptPath){
        super();
        this.beforeDecryptPath=beforeDecryptPath;
        this.afterDecryptPath=afterDecryptPath;
    }

    public static void doDecrypt() {
        List<File> rightFileList=new ArrayList<>();
        List<File> errorFileList=new ArrayList<>();
        //1.读取指定路径下的所有业务报文文件
        List<File> fileList = WriteFileUtil.getFilesByPath(beforeDecryptPath);//不递归文件夹，只取.xml文件
        for (File file : fileList) {
            FileInputStream fis=null;
            InputStreamReader isr=null;
            try{
                JSONObject jsonObject = new JSONObject();
                //1.file内容转为json
                fis=new FileInputStream(file);
                isr=new InputStreamReader(fis,"utf-8");
                jsonObject=parseFileInputStream(isr);
                //2.取出data节点的内容json
                if(jsonObject.containsKey("TransInfo")
                        &&jsonObject.containsKey("Data")) {//湖北省单一窗口
                    Object dataValueObj = jsonObject.get("Data");
                    String dataValueStr = dataValueObj.toString();
                    //3.解码
                    String decodeAfterDataValueStr = Base64Util.decode2String(dataValueStr);
                    //4.从原报文中获取Filename标签的值为解密后报文的文件名，
                    // 因为通道从商务厅接收到的报文文件名是随机的
                    String afterDecryptFileName="";
                    if(jsonObject.containsKey("AddInfo")){
                        net.sf.json.JSONObject addInfoJson = net.sf.json.JSONObject.fromObject(jsonObject.get("AddInfo"));
                        Map<String,String> addInfoMap=addInfoJson;
                        afterDecryptFileName=addInfoMap.get("FileName");
                    }else{
                        afterDecryptFileName=file.getName();
                    }
                    //5.写出为xml文件到指定路径下
                    WriteFileUtil.writeString2File(afterDecryptPath,afterDecryptFileName, decodeAfterDataValueStr);
                    rightFileList.add(file);
                    log.info(file.getName()+"报文解密为"+afterDecryptFileName+"业务报文发往"+afterDecryptPath+"成功！");
                }else{
                    throw new Exception(file.getName()+"报文不符合报文传输通道规定，没有TransInfo和Data标签！");
                }
            }catch (Exception e){
                errorFileList.add(file);
                e.printStackTrace();
                //不抛出异常，不影响其他报文处理
            }finally{
                IOUtils.closeQuietly(isr);
                IOUtils.closeQuietly(fis);
            }
        }//for
        if(rightFileList.size()>0){
            CommonService.movedeleteFile(rightFileList,true);
        }
        if(errorFileList.size()>0){
            CommonService.movedeleteFile(errorFileList,false);
        }
    }

    /**
     * 根据文件输入流解析报文节点并返回json
     */
    public static JSONObject parseFileInputStream(InputStreamReader in) {
        JSONObject returnJson=new JSONObject();
        try{
            JSONObject jsonObject=new JSONObject();
            Document document = saxReader.read(in);
            Element root = document.getRootElement();
            Document2MapUtil.iterateNodes(root, jsonObject);//将xml文件节点及内容转换为json
            returnJson = (JSONObject) jsonObject.get(root.getName());
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            IOUtils.closeQuietly(in);
        }
        return returnJson;
    }
}
